<template>
  <div class="bpmn-editor">
    <el-card class="box-card">
      <template #header>
        <div class="card-header">
          <span>BPMN 流程图编辑器</span>
          <div class="header-actions">
            <el-button-group>
              <el-button type="primary" @click="handleSave">
                <el-icon><Download /></el-icon>保存
              </el-button>
              <el-button type="success" @click="handleImport">
                <el-icon><Upload /></el-icon>导入
              </el-button>
            </el-button-group>
          </div>
        </div>
      </template>

      <div class="editor-container">
        <!-- 画布区域 -->
        <div id="js-canvas" class="canvas-container"></div>

        <!-- 属性面板 -->
        <div class="properties-panel" v-if="selectedElement">
          <h3>属性设置</h3>
          <el-form label-width="100px">
            <el-form-item label="名称">
              <el-input v-model="selectedElement.name" @change="updateElementName" />
            </el-form-item>
            <el-form-item label="描述">
              <el-input type="textarea" v-model="selectedElement.description" @change="updateElementDescription" />
            </el-form-item>
          </el-form>
        </div>
      </div>
    </el-card>

    <!-- 导入对话框 -->
    <el-dialog v-model="importDialogVisible" title="导入 BPMN 文件" width="500px">
      <el-upload
        class="upload-demo"
        drag
        action="#"
        :auto-upload="false"
        :on-change="handleFileChange"
        accept=".bpmn,.xml"
      >
        <el-icon class="el-icon--upload"><upload-filled /></el-icon>
        <div class="el-upload__text">
          拖拽文件到此处或 <em>点击上传</em>
        </div>
        <template #tip>
          <div class="el-upload__tip">
            只能上传 bpmn/xml 文件
          </div>
        </template>
      </el-upload>
      <template #footer>
        <span class="dialog-footer">
          <el-button @click="importDialogVisible = false">取消</el-button>
          <el-button type="primary" @click="confirmImport">确认导入</el-button>
        </span>
      </template>
    </el-dialog>
  </div>
</template>

<script setup>
import { ref, onMounted, onUnmounted } from 'vue'
import BpmnJS from 'bpmn-js/dist/bpmn-viewer.production.min.js'
import { ElMessage } from 'element-plus'
import { Download, Upload, UploadFilled } from '@element-plus/icons-vue'

// BPMN 编辑器实例
const bpmnModeler = ref(null)
// 选中的元素
const selectedElement = ref(null)
// 导入对话框
const importDialogVisible = ref(false)
const importFile = ref(null)

// 创建简单的流程图XML
const getDefaultXml = () => {
  return `<?xml version="1.0" encoding="UTF-8"?>
<bpmn2:definitions xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:bpmn2="http://www.omg.org/spec/BPMN/20100524/MODEL" xmlns:bpmndi="http://www.omg.org/spec/BPMN/20100524/DI" xmlns:dc="http://www.omg.org/spec/DD/20100524/DC" xmlns:di="http://www.omg.org/spec/DD/20100524/DI" xsi:schemaLocation="http://www.omg.org/spec/BPMN/20100524/MODEL BPMN20.xsd" id="sample-diagram" targetNamespace="http://bpmn.io/schema/bpmn">
  <bpmn2:process id="Process_1" isExecutable="false">
    <bpmn2:startEvent id="StartEvent_1"/>
  </bpmn2:process>
  <bpmndi:BPMNDiagram id="BPMNDiagram_1">
    <bpmndi:BPMNPlane id="BPMNPlane_1" bpmnElement="Process_1">
      <bpmndi:BPMNShape id="_BPMNShape_StartEvent_2" bpmnElement="StartEvent_1">
        <dc:Bounds height="36.0" width="36.0" x="412.0" y="240.0"/>
      </bpmndi:BPMNShape>
    </bpmndi:BPMNPlane>
  </bpmndi:BPMNDiagram>
</bpmn2:definitions>`;
}

// 初始化 BPMN 查看器 (只读模式更稳定)
const initBpmnViewer = () => {
  try {
    // 使用 BpmnJS Viewer 而不是 Modeler
    bpmnModeler.value = new BpmnJS({
      container: '#js-canvas'
    });
    
    // 加载默认的 XML
    loadXML(getDefaultXml());
  } catch (error) {
    console.error('初始化 BPMN 编辑器失败:', error);
    ElMessage.error('初始化 BPMN 编辑器失败');
  }
}

// 加载 XML 到查看器
const loadXML = async (xml) => {
  try {
    // 导入 XML（使用 Promise API）
    await bpmnModeler.value.importXML(xml);
    
    // 获取画布和缩放
    const canvas = bpmnModeler.value.get('canvas');
    canvas.zoom('fit-viewport');
    
    // 添加元素点击事件
    const eventBus = bpmnModeler.value.get('eventBus');
    
    eventBus.on('element.click', (e) => {
      if (e.element && e.element.businessObject) {
        selectedElement.value = {
          id: e.element.id,
          name: e.element.businessObject.name || '',
          description: e.element.businessObject.documentation?.[0]?.text || ''
        };
      }
    });
  } catch (error) {
    console.error('加载 XML 失败:', error);
    ElMessage.error('加载 BPMN 失败');
  }
}

// 更新元素名称
const updateElementName = (value) => {
  ElMessage.info('当前处于只读模式，无法编辑流程图');
}

// 更新元素描述
const updateElementDescription = (value) => {
  ElMessage.info('当前处于只读模式，无法编辑流程图');
}

// 保存流程图
const handleSave = async () => {
  if (!bpmnModeler.value) return;

  try {
    // 使用 Promise API 保存 XML
    const { xml } = await bpmnModeler.value.saveXML({ format: true });
    
    // 创建下载链接
    const blob = new Blob([xml], { type: 'application/xml' });
    const url = window.URL.createObjectURL(blob);
    const link = document.createElement('a');
    link.href = url;
    link.download = 'process.bpmn';
    link.click();
    
    window.URL.revokeObjectURL(url);
    ElMessage.success('保存成功');
  } catch (error) {
    console.error('保存流程图失败:', error);
    ElMessage.error('保存失败');
  }
}

// 打开导入对话框
const handleImport = () => {
  importDialogVisible.value = true;
}

// 处理文件选择
const handleFileChange = (file) => {
  importFile.value = file;
}

// 确认导入
const confirmImport = async () => {
  if (!importFile.value || !bpmnModeler.value) {
    ElMessage.warning('请选择要导入的文件');
    return;
  }

  try {
    const reader = new FileReader();
    
    reader.onload = async (e) => {
      try {
        const xml = e.target.result;
        await loadXML(xml);
        ElMessage.success('导入成功');
        importDialogVisible.value = false;
      } catch (error) {
        console.error('导入失败:', error);
        ElMessage.error('导入失败');
      }
    };
    
    reader.readAsText(importFile.value.raw);
  } catch (error) {
    console.error('读取文件失败:', error);
    ElMessage.error('导入失败');
  }
}

onMounted(async () => {
  // 使用延迟确保 DOM 已经渲染
  await new Promise(resolve => setTimeout(resolve, 500));
  await initBpmnViewer();
})

onUnmounted(() => {
  if (bpmnModeler.value) {
    bpmnModeler.value.destroy();
  }
})
</script>

<style>
.bpmn-editor {
  padding: 20px;
}

.card-header {
  display: flex;
  justify-content: space-between;
  align-items: center;
}

.editor-container {
  display: flex;
  height: 600px;
  gap: 20px;
}

.canvas-container {
  flex: 1;
  border: 1px solid #dcdfe6;
  border-radius: 4px;
  position: relative;
  min-height: 500px;
  background-color: white;
}

.properties-panel {
  width: 300px;
  padding: 20px;
  background-color: #f5f7fa;
  border-radius: 4px;
  overflow-y: auto;
}

/* 隐藏不必要的元素 */
.bjs-powered-by {
  display: none !important;
}

/* 控制 SVG 样式 */
#js-canvas svg {
  background-color: white;
}
</style> 